<!--
 * @Description: 
 * @Author: ldx
 * @Date: 2023-03-02 21:05:41
 * @LastEditors: ldx
 * @LastEditTime: 2023-04-27 16:06:06
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <script id="vertex" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec2 a_Pin;
    varying vec2 v_Pin;
    void main(){
      // 顶点位置
      gl_Position = a_Position;
      v_Pin = a_Pin;
    }
  </script>
  <script id="fragment" type="x-shader/x-fragment">
    precision mediump float;
    varying vec2 v_Pin;
    uniform sampler2D u_Sampler;
    void main(){
      // 片元颜色
      gl_FragColor = texture2D(u_Sampler, v_Pin);
    }
  </script>
  <canvas id="canvas"></canvas>
  <script type="module">
    import { initProgram,getViewMatrix } from '../jsm/utils.js'
    import Poly from '../jsm/Poly.js'
    import { Matrix4, Vector3, Quaternion } from 'https://unpkg.com/three/build/three.module.js';
    const canvas = document.querySelector('#canvas')
    // 设置canvas容器的宽高
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight
    // 获取webgl上下文
    const gl = canvas.getContext('webgl');
    // 声明将来用来清空绘图区的颜色。分别对应r,g,b,a
    gl.clearColor(0, 0, 0, 1)
    // 使用之前声明的颜色，清空绘图区
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 初始化程序对象
    initProgram(gl)

    const vertices = new Float32Array([
      -0.2,0.4,0, 0,2,
      -0.2,0,0, 0,0,
      0.2,0.4,0,  2,2,
      0.2,0,0,  2,0
    ])
    // 元素字节数，一个元素占几个字节
    const elementBytes = vertices.BYTES_PER_ELEMENT
    // 创建缓冲区
    const vertexBuffer = gl.createBuffer()
    // 绑定缓冲区
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
    // 写入缓冲数据
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
    // 获取attribute变量并修改
    const a_Position = gl.getAttribLocation(gl.program, 'a_Position')
    // 修改attribute变量
    gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 5*elementBytes, 0)
    // 启用当前绑定缓冲区的顶点数组
    gl.enableVertexAttribArray(a_Position)

    
    // 获取attribute变量并修改
    const a_Pin = gl.getAttribLocation(gl.program, 'a_Pin')
    // 修改attribute变量
    gl.vertexAttribPointer(a_Pin, 2, gl.FLOAT, false, 5*elementBytes, 3*elementBytes)
    // 启用当前绑定缓冲区的顶点数组
    gl.enableVertexAttribArray(a_Pin)

    gl.enable(gl.BLEND)
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    const img = new Image()
    img.src = './images/erha.jpg'
    // 激活纹理单元
    gl.activeTexture(gl.TEXTURE0);
    // 创建纹理对象
    const texture = gl.createTexture();
    // 将 WebGLTexture 绑定到目标纹理对象上，比如 gl.TEXTURE_2D。
    gl.bindTexture(gl.TEXTURE_2D, texture)
    /* 
      * 图像预处理
        栅格坐标系和uv坐标系的y轴相反，这里是将像素数据的垂直翻转模式设置为开启状态，
        这样加载的纹理图像数据会被垂直翻转。
    */
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1)
    img.onload = ()=>{
      // 将图像数据加载到纹理对象中
      /** 
       * 参数解析如下：
        target: 表示纹理对象的类型，可以是 gl.TEXTURE_2D 或 gl.TEXTURE_CUBE_MAP。在这里我们只考虑 gl.TEXTURE_2D 类型的纹理对象。
        level: 表示纹理对象的级别，通常为 0。纹理对象可以有多个级别，每个级别都是一个不同的 MIP（multum-in-parvo，迷你图）映射，通常是用于细节层次渲染。
        internalFormat: 表示纹理对象的内部格式，用于指定图像数据在纹理对象中的存储方式。常用的内部格式有 gl.RGBA 和 gl.RGB，表示图像使用 RGBA 或 RGB 颜色格式存储。
        format: 表示图像数据的格式，用于指定图像数据在纹理对象中的存储方式。常用的格式有 gl.RGBA 和 gl.RGB，表示图像使用 RGBA 或 RGB 颜色格式存储。
        type: 表示图像数据的类型，用于指定图像数据在纹理对象中的存储方式。常用的类型有 gl.UNSIGNED_BYTE 和 gl.FLOAT，表示图像数据是无符号字节或浮点数。
        source: 表示图像数据的源，可以是 HTMLImageElement、HTMLCanvasElement、HTMLVideoElement 或者 ImageData。它包含了要加载到纹理对象中的图像数据。
        在 gl.texImage2D() 中，internalFormat 和 format 可以是同一个值，也可以是不同的值，这取决于你要加载的图像数据的格式和纹理对象的格式是否匹配。
        type 参数通常与 internalFormat 相关联，例如，如果 internalFormat 是 gl.RGBA，那么 type 参数通常是 gl.UNSIGNED_BYTE。
       */
      gl.texImage2D(
        gl.TEXTURE_2D,
        0,
        gl.RGBA,
        gl.RGBA,
        gl.UNSIGNED_BYTE,
        img
      )
      /**
       *  gl.texParameteri(target, pname, param) 是WebGL中设置纹理参数的函数。
          target 表示纹理的目标，可以是以下值之一：
          gl.TEXTURE_2D：二维纹理
          gl.TEXTURE_CUBE_MAP_POSITIVE_X：正 X 轴的立方体贴图面
          gl.TEXTURE_CUBE_MAP_NEGATIVE_X：负 X 轴的立方体贴图面
          gl.TEXTURE_CUBE_MAP_POSITIVE_Y：正 Y 轴的立方体贴图面
          gl.TEXTURE_CUBE_MAP_NEGATIVE_Y：负 Y 轴的立方体贴图面
          gl.TEXTURE_CUBE_MAP_POSITIVE_Z：正 Z 轴的立方体贴图面
          gl.TEXTURE_CUBE_MAP_NEGATIVE_Z：负 Z 轴的立方体贴图面
          pname 表示要设置的纹理参数名称，可以是以下值之一：
          gl.TEXTURE_MIN_FILTER：设置纹理缩小过滤器
          gl.TEXTURE_MAG_FILTER：设置纹理放大过滤器
          gl.TEXTURE_WRAP_S：设置纹理水平包裹模式
          gl.TEXTURE_WRAP_T：设置纹理垂直包裹模式
          gl.TEXTURE_WRAP_R：设置立方体纹理的深度包裹模式
          gl.TEXTURE_BASE_LEVEL：设置生成 mipmap 的最低级别
          gl.TEXTURE_MAX_LEVEL：设置生成 mipmap 的最高级别
          param 表示要设置的参数值，具体取值与 pname 相关，常用的有：
          gl.NEAREST：使用最近邻过滤器
          gl.LINEAR：使用线性过滤器
          gl.REPEAT：重复纹理
          gl.CLAMP_TO_EDGE：将纹理坐标限制在边界范围内
          gl.MIRRORED_REPEAT：镜像重复纹理
          gl.NEAREST_MIPMAP_NEAREST：使用最近邻过滤器，在最近的 mipmap 级别中选择最近的像素
          gl.LINEAR_MIPMAP_NEAREST：使用线性过滤器，在最近的 mipmap 级别中选择最近的像素
          gl.NEAREST_MIPMAP_LINEAR：使用最近邻过滤器，在两个最近的 mipmap 级别之间进行线性插值
          gl.LINEAR_MIPMAP_LINEAR：使用线性过滤器，在两个最近的 mipmap 级别之间进行线性插值
      */
      gl.texParameteri(
        gl.TEXTURE_2D,
        gl.TEXTURE_MIN_FILTER,
        gl.LINEAR
      )
      gl.texParameteri(
        gl.TEXTURE_2D,
        gl.TEXTURE_WRAP_S,
        gl.MIRRORED_REPEAT
      )
      gl.texParameteri(
        gl.TEXTURE_2D,
        gl.TEXTURE_WRAP_T,
        gl.CLAMP_TO_EDGE
      )
      const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler')
      gl.uniform1i(u_Sampler, 0)

       // 使用之前声明的颜色，清空绘图区
      gl.clear(gl.COLOR_BUFFER_BIT)
      // 绘制一系列三角形
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
    }

   
    
  </script>
</body>

</html>